<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import { ElMessage, ElUpload } from 'element-plus'
import type { FormInstance, UploadFile, UploadInstance, UploadRawFile } from 'element-plus'
import { UploadFilled } from '@element-plus/icons-vue'
import { addUserListService } from '@/api/user'
import { getClassnameListService } from '@/api/education/classname'
import { TClass } from '@/Types/education'
import * as XLSX from 'xlsx'
import Loading from '@/components/Animation/loading.vue'

const props = defineProps({
	dialogVisible: {
		type: Boolean,
		default: false
	}
})

const emit = defineEmits(['closeDialog', 'update:dialogVisible'])

const localVisible = ref(false)

// 监听props变化更新本地状态
watch(
	() => props.dialogVisible,
	(val) => {
		localVisible.value = val
	}
)

// 监听本地状态变化触发更新事件
watch(
	() => localVisible.value,
	(val) => {
		if (!val) {
			emit('update:dialogVisible', false)
			emit('closeDialog', false)
		}
	}
)

// 上传相关
const uploadRef = ref<UploadInstance>()
const fileList = ref<UploadFile[]>([])
const uploadLoading = ref(false)

// 班级相关
const classList = ref<TClass[]>([])
const selectedClassId = ref('')

// 解析后的数据
const parsedData = ref<any[]>([])
const showPreview = ref(false)
const previewData = ref<any[]>([])

const formRef = ref<FormInstance>()

// 加载状态控制
const isParsingFile = ref(false)
const isUploadingData = ref(false)
const loadingText = ref('正在处理中...')

// 获取班级列表
const fetchClassList = async () => {
	try {
		const res = await getClassnameListService()
		if (res.data.code === 1) {
			classList.value = res.data.data
		} else {
			ElMessage.error('获取班级列表失败')
		}
	} catch (error) {
		console.error('获取班级列表失败:', error)
		ElMessage.error('获取班级列表失败')
	}
}

// 格式化学历
const formatLevel = (item: any) => {
	switch (item) {
		case 'undergrad':
			return '本科'
		case 'vocEd':
			return '硕士'
		default:
			return '未知'
	}
}

// 格式化班级显示
const formatClassLabel = (item: TClass) => {
	if (!item) return ''
	return `${formatLevel(item.level)}${item.grade}级${item.academy}${item.major}${item.classname}班`
}

// 生命周期钩子
onMounted(() => {
	fetchClassList()
})

// 文件上传限制
const beforeUpload = (file: UploadRawFile) => {
	const isExcel =
		file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
		file.type === 'application/vnd.ms-excel'
	if (!isExcel) {
		ElMessage.error('只能上传Excel文件!')
		return false
	}

	const isLt5M = file.size / 1024 / 1024 < 5
	if (!isLt5M) {
		ElMessage.error('文件大小不能超过5MB!')
		return false
	}

	return true
}

// 移除文件
const handleRemove = () => {
	fileList.value = []
	parsedData.value = []
	showPreview.value = false
}

// 上传文件变更
const handleChange = async (file: UploadFile, files: UploadFile[]) => {
	fileList.value = files
	if (file.raw) {
		await parseExcelFile(file.raw)
	}
}

// 解析Excel文件
const parseExcelFile = async (file: File) => {
	try {
		isParsingFile.value = true
		loadingText.value = '正在解析Excel文件...'

		const reader = new FileReader()

		reader.onload = (e) => {
			try {
				const data = e.target?.result
				const workbook = XLSX.read(new Uint8Array(data as ArrayBuffer), { type: 'array' })
				const worksheet = workbook.Sheets[workbook.SheetNames[0]]

				// 解析Excel数据，处理特殊结构
				const excelData = processExcelData(worksheet)

				if (excelData.length === 0) {
					ElMessage.warning('Excel文件中没有有效数据')
					isParsingFile.value = false
					return
				}

				parsedData.value = excelData

				// console.log(parsedData.value)
				generatePreviewData()
				showPreview.value = true

				ElMessage.success('Excel文件解析成功')
				isParsingFile.value = false
			} catch (error) {
				// console.error('解析Excel文件失败:', error)
				ElMessage.error('解析Excel文件失败')
				isParsingFile.value = false
			}
		}

		reader.onerror = () => {
			ElMessage.error('读取文件失败')
			isParsingFile.value = false
		}

		reader.readAsArrayBuffer(file)
	} catch (error) {
		// console.error('解析Excel文件错误:', error)
		ElMessage.error('解析Excel文件错误')
		isParsingFile.value = false
	}
}

// 处理特殊结构的Excel数据
const excelData = ref<any[]>([])
const processExcelData = (worksheet: XLSX.WorkSheet) => {
	// 先获取原始数据
	const rawData = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' })

	// 找到表头所在行和数据起始行
	let headerRowIndex = -1
	let dataStartRowIndex = -1

	for (let i = 0; i < rawData.length; i++) {
		excelData.value = rawData[i] as any[]
		// 查找包含"序号"和"姓名"的行作为表头行
		if (
			// excelData.value.includes('序号') &&
			excelData.value.includes('姓名') &&
			excelData.value.includes('学号')
		) {
			headerRowIndex = i
			dataStartRowIndex = i + 1
			break
		}
	}

	if (headerRowIndex === -1 || dataStartRowIndex === -1) {
		ElMessage.warning('Excel格式不正确，找不到表头')
		return []
	}

	// 获取表头和标识索引
	const headers = rawData[headerRowIndex] as string[]
	const nameIndex = headers.indexOf('姓名')
	const idIndex = headers.indexOf('学号')
	const phoneIndex = headers.indexOf('联系方式')

	if (nameIndex === -1 || idIndex === -1) {
		ElMessage.warning('Excel必须包含姓名和学号列')
		return []
	}

	// 提取有效数据并处理
	const result = []
	for (let i = dataStartRowIndex; i < rawData.length; i++) {
		const row = rawData[i] as any[]

		// 跳过空行或无效行
		if (!row[nameIndex] || !row[idIndex]) continue

		// 构建用户数据对象
		const userData = {
			uname: row[nameIndex],
			typeNumber: row[idIndex],
			phoneNumber: phoneIndex !== -1 ? row[phoneIndex] : '',
			// 账号和密码默认使用学号
			account: row[idIndex],
			password: row[idIndex]
		}

		result.push(userData)
	}

	return result
}

// 生成预览数据
const generatePreviewData = () => {
	if (parsedData.value.length === 0) return

	// 只显示前5条数据作为预览
	previewData.value = parsedData.value.map((item, index) => ({
		index: index + 1,
		...item
	}))
}

// 重置表单与文件数据
const resetFormData = () => {
	fileList.value = []
	parsedData.value = []
	previewData.value = []
	showPreview.value = false
	selectedClassId.value = ''
	formRef.value?.resetFields()
}

// 提交表单
const submitUpload = async () => {
	if (fileList.value.length === 0) {
		ElMessage.warning('请先选择要上传的Excel文件')
		return
	}

	if (!selectedClassId.value) {
		ElMessage.warning('请选择班级')
		return
	}

	if (parsedData.value.length === 0) {
		ElMessage.warning('没有有效的用户数据')
		return
	}

	isUploadingData.value = true
	loadingText.value = '正在导入用户数据...'
	uploadLoading.value = true

	try {
		// 构建用户数据列表，每个用户包含班级ID
		const userData = parsedData.value.map((user) => ({
			...user,
			classId: [selectedClassId.value],
			userTypeId: 1 // 默认为学生类型
		}))

		// console.log(userData)

		// 直接提交用户数据数组
		const res = await addUserListService(userData)

		if (res.data.code === 1) {
			ElMessage.success('批量导入用户成功')
			resetFormData()
			localVisible.value = false
			emit('closeDialog', true) // 成功时返回true
		} else {
			ElMessage.error(res.data.msg || '批量导入用户失败')
		}
	} catch (error) {
		console.error('批量导入用户失败:', error)
		ElMessage.error('批量导入用户失败')
	} finally {
		isUploadingData.value = false
		uploadLoading.value = false
	}
}

// 当对话框关闭时重置表单数据
watch(
	() => localVisible.value,
	(val) => {
		if (!val) {
			resetFormData()
			emit('update:dialogVisible', false)
			emit('closeDialog', false)
		}
	}
)
</script>

<template>
	<el-dialog
		v-model="localVisible"
		title="批量导入用户"
		width="600px"
		:close-on-click-modal="false"
		:destroy-on-close="true"
	>
		<el-form ref="formRef">
			<div class="upload-container">
				<el-upload
					ref="uploadRef"
					class="upload-excel"
					action="#"
					:auto-upload="false"
					:limit="1"
					:on-change="handleChange"
					:on-remove="handleRemove"
					:before-upload="beforeUpload"
					:file-list="fileList"
					accept=".xlsx,.xls"
				>
					<template #trigger>
						<el-button type="primary" :icon="UploadFilled">选择文件</el-button>
					</template>
					<template #tip>
						<div class="el-upload__tip">请上传Excel文件(xls/xlsx), 文件大小不超过5MB</div>
					</template>
				</el-upload>
			</div>

			<!-- 数据预览 -->
			<div v-if="showPreview && previewData.length > 0" class="data-preview">
				<h4>数据预览（共 {{ parsedData.length }} 条数据）</h4>
				<el-table :data="previewData" border style="width: 100%" max-height="200">
					<el-table-column type="index" label="序号" width="60" />
					<el-table-column prop="uname" label="姓名" width="100" />
					<el-table-column prop="typeNumber" label="学号" width="120" />
					<el-table-column prop="phoneNumber" label="联系方式" width="120" />
					<el-table-column prop="account" label="账号" width="120" />
					<el-table-column prop="password" label="密码" width="120" />
				</el-table>
			</div>

			<!-- 班级选择 -->
			<div class="class-selector">
				<el-form-item label="选择班级" required>
					<el-select
						v-model="selectedClassId"
						placeholder="请选择班级"
						style="width: 60%"
						filterable
					>
						<el-option
							v-for="item in classList"
							:key="item.classId"
							:label="formatClassLabel(item)"
							:value="item.classId"
						/>
					</el-select>
				</el-form-item>
			</div>

			<div class="import-info">
				<h4>导入说明</h4>
				<ul>
					<li>支持批量导入学生、教师等用户信息</li>
					<li>Excel中必须包含：姓名、学号</li>
					<li>如未提供账号和密码，将使用学号作为默认账号和密码</li>
					<li>导入前请确保选择了正确的班级</li>
					<li>数据量较大时可能需要等待较长时间</li>
				</ul>
			</div>
		</el-form>

		<template #footer>
			<span class="dialog-footer">
				<el-button @click="localVisible = false">取消</el-button>
				<el-button type="primary" @click="submitUpload" :loading="uploadLoading">导入</el-button>
			</span>
		</template>

		<!-- 加载组件 -->
		<Loading v-model="isParsingFile" :text="loadingText" target="container" />
		<Loading v-model="isUploadingData" :text="loadingText" target="container" />
	</el-dialog>
</template>

<style lang="scss" scoped>
.upload-container {
	display: flex;
	justify-content: center;
	margin-bottom: 20px;
	position: relative;

	.upload-excel {
		width: 100%;
	}
}

.class-selector {
	margin: 20px 0;
	position: relative;
}

.data-preview {
	margin: 20px 0;
	position: relative;

	h4 {
		margin-top: 0;
		margin-bottom: 10px;
		color: #606266;
	}

	.preview-note {
		font-size: 12px;
		color: #909399;
		margin-top: 5px;
		text-align: right;
	}
}

.import-info {
	border: 1px dashed #dcdfe6;
	border-radius: 4px;
	padding: 10px 15px;
	background-color: #f9f9f9;
	margin-top: 15px;
	position: relative;

	h4 {
		margin-top: 0;
		margin-bottom: 10px;
		color: #606266;
	}

	ul {
		margin: 0;
		padding-left: 20px;
		color: #606266;

		li {
			margin-bottom: 5px;
			font-size: 14px;
			line-height: 1.5;
		}
	}
}

.dialog-footer {
	display: flex;
	justify-content: flex-end;
	width: 100%;
	gap: 10px;
}
</style>
